﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using TweetSharp;
using Twitter4Umbraco.Extensions;

namespace Twitter4Umbraco.Controls
{
	public class TweetTemplateContainer : Control, INamingContainer
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="TweetTemplateContainer"/> class.
		/// </summary>
		/// <param name="tweet">The tweet.</param>
		public TweetTemplateContainer(TwitterStatus tweet)
		{
			this.Tweet = tweet;
		}

		[Bindable(true)]
		public TwitterStatus Tweet { get; set; }
	}

	/// <summary>
	/// A control to embed a Twitter status into a HTML page.
	/// </summary>
	[DefaultProperty("StatusId")]
	[ParseChildren(true)]
	[ToolboxData("<{0}:EmbedTweet runat=server></{0}:EmbedTweet>")]
	public class EmbedTweet : WebControl, INamingContainer
	{
		[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
		[TemplateContainer(typeof(TweetTemplateContainer))]
		[TemplateInstance(TemplateInstance.Single)]
		public ITemplate Template { get; set; }

		protected TweetTemplateContainer TweetTemplateContainer;

		/// <summary>
		/// Gets or sets the status id.
		/// </summary>
		/// <value>The status id.</value>
		[Bindable(true)]
		[Category("Data")]
		[DefaultValue("")]
		[Description("The Id of the status update")]
		public string StatusId { get; set; }

		private string statusUrl;

		/// <summary>
		/// Gets or sets the status URL.
		/// </summary>
		/// <value>The status URL.</value>
		[Bindable(true)]
		[Category("Data")]
		[DefaultValue("")]
		[Description("The Url of the status update")]
		public string StatusUrl
		{
			get
			{
				if (string.IsNullOrEmpty(this.statusUrl) && !string.IsNullOrEmpty(this.StatusId) && !string.IsNullOrEmpty(this.Username))
				{
					return Common.GetStatusUrl(this.StatusId, this.Username);
				}

				return this.statusUrl;
			}

			set
			{
				string statusId, username;

				this.ParseStatusUrl(value, out username, out statusId);

				this.statusUrl = value;
				this.Username = username;
				this.StatusId = statusId;
			}
		}

		/// <summary>
		/// Gets or sets the tweet.
		/// </summary>
		/// <value>The tweet.</value>
		[Bindable(true)]
		[Category("Data")]
		[Description("The status update itself")]
		public TwitterStatus Tweet { get; set; }

		/// <summary>
		/// Gets or sets the username.
		/// </summary>
		/// <value>The username.</value>
		[Bindable(true)]
		[Category("Data")]
		[DefaultValue("")]
		[Description("The username")]
		public string Username { get; set; }

		/// <summary>
		/// Renders the HTML opening tag of the control to the specified writer. This method is used primarily by control developers.
		/// </summary>
		/// <param name="writer">A <see cref="T:System.Web.UI.HtmlTextWriter"/> that represents the output stream to render HTML content on the client.</param>
		public override void RenderBeginTag(HtmlTextWriter writer)
		{
			// base.RenderBeginTag(writer);
		}

		/// <summary>
		/// Renders the HTML closing tag of the control into the specified writer. This method is used primarily by control developers.
		/// </summary>
		/// <param name="writer">A <see cref="T:System.Web.UI.HtmlTextWriter"/> that represents the output stream to render HTML content on the client.</param>
		public override void RenderEndTag(HtmlTextWriter writer)
		{
			// base.RenderEndTag(writer);
		}

		/// <summary>
		/// Raises the <see cref="E:System.Web.UI.Control.Load"/> event.
		/// </summary>
		/// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param>
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			// TODO: [LK] Decide which has precendence: StatusId or StatusUrl
			// or if StatuIs is empty, check if StatusUrl is empty (meaning store the set value in a private string)
			if (string.IsNullOrEmpty(this.StatusId) && !string.IsNullOrEmpty(this.statusUrl))
			{
				this.StatusUrl = this.statusUrl;
			}

			// check if a tweet has already been assigned, and that the status id isn't empty.
			if (this.Tweet == null && !string.IsNullOrEmpty(this.StatusId))
			{
				this.Tweet = Common.GetTweet(this.StatusId);
			}

			// check if a template has been set - and tweet is available.
			if (this.Template != null && this.Tweet != null)
			{
				this.TweetTemplateContainer = new TweetTemplateContainer(this.Tweet);
				this.Template.InstantiateIn(this.TweetTemplateContainer);
				this.Controls.Add(this.TweetTemplateContainer);

				// ... and don't forget to DataBind!
				this.DataBind();
			}
		}

		/// <summary>
		/// Renders the contents of the control to the specified writer. This method is used primarily by control developers.
		/// </summary>
		/// <param name="writer">A <see cref="T:System.Web.UI.HtmlTextWriter"/> that represents the output stream to render HTML content on the client.</param>
		protected override void RenderContents(HtmlTextWriter writer)
		{
			if (this.DesignMode)
			{
				// in design mode, don't render the control - just text/message.
			    writer.Write("uTwitter: Embedded Tweet");
			}
			else if (this.TweetTemplateContainer != null)
			{
				// if the template container is set, then render custom template.
				this.TweetTemplateContainer.RenderControl(writer);
			}
			else if (this.Tweet != null)
			{
				// otherwise fall back on Blackbird Pie!
				writer.WriteLine(Common.BakeTweet(this.Tweet));
			}
		}

		private void ParseStatusUrl(string url, out string username, out string statusId)
		{
			// remove the domain name
			if (url.Contains(Common.TWITTER_URL))
			{
				url = url.Replace(Common.TWITTER_URL, string.Empty);
			}

			// 
			string ajaxHash = "#!/";
			if (url.Contains(ajaxHash))
			{
				url = url.Replace(ajaxHash, string.Empty);
			}

			var parts = url.Split('/');
			if (parts.Length >= 3)
			{
				username = parts[0];
				statusId = parts[2];

				return;
			}

			// fallback - default values
			username = statusId = string.Empty;
		}
	}
}
